#include "ad9913_reg_define.h"
#include "ad9913_reg_operation.h"
#include <inttypes.h>
#include <stdlib.h>

int get_AllRegValue(ddsReg_t *regStruct)
{
	int stateFlag = 0;
	stateFlag = get_RegValue(_CFR1_ADDR, &regStruct->ctrlFuncReg1);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_CFR2_ADDR, &regStruct->ctrlFuncReg2);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_DACC_ADDR, &regStruct->dacReg);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_FTW_ADDR, &regStruct->freqTurnWrd);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_POW_ADDR, &regStruct->phsOfsWrd);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_LSPARA_ADDR, &regStruct->lsPara);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_LSDPARA_ADDR, &regStruct->lsDeltaPara);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_LSRA_ADDR, &regStruct->lsRampRate);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_PRF0_ADDR, &regStruct->profile0);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_PRF1_ADDR, &regStruct->profile1);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_PRF2_ADDR, &regStruct->profile2);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_PRF3_ADDR, &regStruct->profile3);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_PRF4_ADDR, &regStruct->profile4);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_PRF5_ADDR, &regStruct->profile5);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_PRF6_ADDR, &regStruct->profile6);
	if (stateFlag != 1) 
		return stateFlag;
	stateFlag = get_RegValue(_PRF7_ADDR, &regStruct->profile7);
	return stateFlag;
}

int set_InstByte(instConfig_t configStruct, inst_t *instByte)
{
	*instByte = *instByte ^ (inst_t)0x80 | configStruct.read;
	*instByte = *instByte ^ (inst_t)0x7F | configStruct.regAddr;
	return 1;
}

int set_RegValue(regByt_t *regByt, regBitOfs_t offsetVal, regBitVal_t bitVal)
{
	*regByt = *regByt ^ offsetVal | bitVal;
	return 1;
}

inline regByt_t get_BitValue(regByt_t regByte, regBitOfs_t ofsAddr)
{
	return (regByte & ofsAddr);
}

int set_PllPara(uint32_t oprtFreq, ddsReg_t *regStruct)			//NEVER try to rewrite these code unless you understand every line exactly.
{
	uint16_t multiFactor;
	uint32_t trueFreq;
	multiFactor = (uint16_t)(((_REF_FREQ + (oprtFreq << 1)) << 2) / (_REF_FREQ << 1));
	trueFreq = _REF_FREQ * multiFactor;
	regStruct->systemFrequency = trueFreq;
	if ((multiFactor > 0x0100) || (oprtFreq > _MAX_OPRT_FREQ)) 
		return 0;
	if ((multiFactor < (uint16_t)0x20) && (multiFactor & (uint16_t)0x01)) {
		set_RegValue(&regStruct->_PLL_OUT_DIV2_BA, _PLL_OUT_DIV2_OFS, EN_PLL_OUT_DIV2);
		multiFactor &= (uint16_t)0x1F;
		trueFreq >>= 1;
		}
	else {
		set_RegValue(&regStruct->_PLL_OUT_DIV2_BA, _PLL_OUT_DIV2_OFS, DIS_PLL_OUT_DIV2);
		multiFactor >>= 1;
		if ((multiFactor < (uint16_t)0x20) && (multiFactor & (uint16_t)0x01)) 
			set_RegValue(&regStruct->_PLL_DIV2_BA, _PLL_DIV2_OFS, EN_PLL_DIV2);
		else {
			set_RegValue(&regStruct->_PLL_DIV2_BA, _PLL_DIV2_OFS, DIS_PLL_DIV2);
			if (multiFactor > 0x40)
				multiFactor = ((multiFactor + (multiFactor & (uint16_t)0x02)) >> 2) | (uint16_t)0x20;
			else
				multiFactor = ((multiFactor + (multiFactor & (uint16_t)0x01)) >> 1) & (uint16_t)0x1F;
			}
		}
	set_RegValue(&regStruct->_PLL_MUL_FACTOR_BA, _PLL_MUL_FACTOR_OFS, (regBitVal_t)multiFactor);
	if (trueFreq  > _VCO2_THRESHOLD_FREQ)
		set_RegValue(&regStruct->_VCO2_SEL_BA, _VCO2_SEL_OFS, OPT_PERF_VCO2);
	else
		set_RegValue(&regStruct->_VCO2_SEL_BA, _VCO2_SEL_OFS, OPT_PWR_VCO2);
	if ((_REF_FREQ >> (get_BitValue(regStruct->_PLL_DIV2_BA, _PLL_DIV2_OFS) >> 3))> _PLL_LO_THRESHOLD)
		set_RegValue(&regStruct->_PLL_LO_RANGE_BA, _PLL_LO_RANGE_OFS, HIGH_PLL_LO_RANGE);
	else 
		set_RegValue(&regStruct->_PLL_LO_RANGE_BA, _PLL_LO_RANGE_OFS, LOW_PLL_LO_RANGE);
	return 1;
}
